package br.usp.icmc.lasdpc.gem.com;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;

/**
 * Utilitary class for communication proposes.
 * 
 * @author Lourenco Alves
 *
 */
public class Util {

	/**
	 * This function gets all IP interfaces and try to guess that is safer for 
	 * communication. By `safer' is intended to point to the IP interface that
	 * can send data to the Internet as well as to the Ethernet -- in other words
	 * send data to WAN and LAN.
	 * <p>
	 * To a physical network card can be assigned many IPs, so its common to a 
	 * single one be listed as having an IP for IPv4, other for IPv6, other for
	 * VPN and so on.
	 * <p>
	 * When IP interfaces are available, it returns InetAddress.getLocalHost, 
	 * which will pass the localhost loopback. Case one is found, return it. 
	 * Otherwise, will exist others and the guessing is choose the last one, 
	 * which is probably the oldest connection.
	 * <p>
	 * The guessing may fail. And it will known fail when running on MS Windows
	 * and VirtualBox is installed. VirtualBox make a virtual interface, which
	 * can be up before other interfaces bring up.   
	 * 
	 * @return the guessed IP address
	 * @throws SocketException
	 * @throws UnknownHostException
	 */
	public static InetAddress getLocalHost() throws SocketException, UnknownHostException {
		ArrayList<InetAddress> addresses = new ArrayList<InetAddress>();

		// put IP interfaces on addresses and ignore loopback address.
		Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
		for (NetworkInterface netint : Collections.list(nets)) {
			for (InetAddress inetAddress : Collections.list(netint.getInetAddresses())) {
				if (!inetAddress.isLoopbackAddress()) {
					addresses.add(inetAddress);
				}
			}
		}
		
		if (addresses.size() == 0) {
			System.err.println("Warning: Only loopback is present. It will use it.");
			return InetAddress.getLocalHost();
		} else if (addresses.size() == 1) {
			// Return the IP that is not the loopback.
			return addresses.get(0);
		} else {
			System.err.println("Warning: More than one ip address for this host. Adopting: " + 
					addresses.get(addresses.size() - 1).getHostAddress());

			System.out.println("Listing all available ip addresses:");
			for (InetAddress ia : addresses) {
				System.out.println(ia.getHostAddress());
			}
			
			return addresses.get(addresses.size() - 1);
		}
	}
	
}
